﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Collections;

namespace Cosmos.Hardware
{
    public abstract class VGAScreen : Hardware
    {
        public static List<Color> _RegisteredColours = new List<Color>();
        public static Size _ScreenResolution;

        public static uint[,] pixels;

        public static uint[] EmptyUInt = new uint[] { };

        public static VGAScreen.SetPixelDelegate SetPixel = new SetPixelDelegate(SetPixelNoMode);

        public VGAScreen() { }

        protected static void SetPaletteAt(int index, Color value)
        {
            /*if (_RegisteredColours.Length - 1 < index) // Add
            {
                ((IList)_RegisteredColours).Insert(index, value);
            }
            else // Change
            {*/
                _RegisteredColours[index] = value;
            //}
        }
        protected static void InitializePalette(int size)
        {
            _RegisteredColours = new List<Color>(size);
            for (int i = 0; i < size; i++)
            {
                ((IList)_RegisteredColours).Add(Color.Black);
            }
        }

        public static int Colors { get { return _RegisteredColours.Capacity; } }
        public static int PixelHeight { get { return _ScreenResolution.Width; } }
        public static int PixelWidth { get { return _ScreenResolution.Height; } }

        public static void Clear(int colour)
        {
            for (uint x = 0; x < _ScreenResolution.Width; x++)
            {
                for (uint y = 0; y < _ScreenResolution.Height; y++)
                {
                    SetPixel(x, y, (uint)colour);
                }
            }
        }
        //public static MemoryAddressSpace GetAddressSpace();
        public static Color GetPaletteEntry(int index)
        {
            return _RegisteredColours[index];
        }
        public static uint GetPixel320x200x8(uint x, uint y)
        {
            return pixels[x, y];
        }
        public static void SetMode320x200x8()
        {
            InitializePalette(8);
            _ScreenResolution = new Size(320, 200);
            pixels = new uint[320, 200];
            if (VGACall != null) VGACall(VGAEventType.SetMode, EmptyUInt);
        }
        public static void SetMode320x240x4()
        {
            InitializePalette(4);
            _ScreenResolution = new Size(320, 240);
            pixels = new uint[320, 240];
            if (VGACall != null) VGACall(VGAEventType.SetMode, EmptyUInt);
        }
        public static void SetMode640x480x2()
        {
            InitializePalette(2);
            _ScreenResolution = new Size(640, 480);
            pixels = new uint[640, 480];
            if (VGACall != null) VGACall(VGAEventType.SetMode, EmptyUInt);
        }
        public static void SetMode640x480x4()
        {
            InitializePalette(4);
            _ScreenResolution = new Size(640, 480);
            pixels = new uint[640, 480];
            if (VGACall != null) VGACall(VGAEventType.SetMode, EmptyUInt);
        }
        public static void SetMode720x480x16()
        {
            InitializePalette(16);
            _ScreenResolution = new Size(720, 480);
            pixels = new uint[720, 480];
            if (VGACall != null) VGACall(VGAEventType.SetMode, EmptyUInt);
        }
        /*public static void SetColorMode(int colors)
        {
            InitializePalette(colors);
        }*/
        //public static void SetPalette(int index, byte[] pallete);
        public static void SetPaletteEntry(int index, Color color)
        {
            try
            {
                SetPaletteAt(index, color);
                if (VGACall != null) VGACall(VGAEventType.SetPalette, EmptyUInt);
            }
            catch { }
        }
        public static void SetPaletteEntry(int index, byte r, byte g, byte b)
        {
            SetPaletteEntry(index, Color.FromArgb(r, g, b));
        }
        public static void SetPixel320x200x8(uint x, uint y, uint c)
        {
            SetPixel(x, y, c);
        }
        public static void SetPixel640x480x4(uint x, uint y, uint c)
        {
            SetPixel(x, y, c);
        }
        //public static void SetTextMode(VGAScreen.TextSize aSize);
        //public static void Test();

        public enum TextSize
        {
            Size40x25 = 0,
            Size40x50 = 1,
            Size80x25 = 2,
            Size80x50 = 3,
            Size90x30 = 4,
            Size90x60 = 5,
        }

        public delegate void SetPixelDelegate(uint x, uint y, uint c);

        public enum VGAEventType
        {
            SetMode = 0x01,
            SetPixel = 0x02,
            SetPalette
        }

        public delegate void VGAEventArguments(VGAEventType type, params uint[] args);

        public static event VGAEventArguments VGACall;

        private static void SetPixelNoMode(uint x, uint y, uint c)
        {
            if (VGACall != null) VGACall(VGAEventType.SetPixel, x, y, c);
        }
    }
}
